#include <algorithm>
#include <iostream>
#include "Master.h"
#include "TwoWayList.cc"

using namespace std;

MasterImp::MasterImp(void)
#ifdef DEBUG_EVPROC
: EventProcessorImp(true,"Master") // comment to remove debug
#endif
{
  
  // register the message function
  RegisterMessageProcessor(DieMessage::type, &Die, 0 /* priority */);

  RegisterMessageProcessor(GenDoneMessage::type, &GenDone, 1 /* priority */);
  
  RegisterMessageProcessor(ReadyMessage::type, &WorkerReady, 2 /* priority */);
  
  RegisterMessageProcessor(FillMessage::type, &PushNumber, 3 /* priority */);
  
  RegisterMessageProcessor(DoneMessage::type, &SumDone, 4 /* priority */);

  sum = 0;
	
  generatorsDone = false;

  current = 0;

 //CreateWorkers();	

}
#if 1
void MasterImp::CreateWorkers(){

	EventProcessor myInterfClone;
	myInterfClone.CopyFrom(myInterface);

	DistributedCounter dCounter(NUM_WORKERS);

	//TwoWayList <EventProcessor> myWorkers;
	//int start = 0;
	for(int i = 0;i < NUM_WORKERS;++i){
		Worker newWorker(myInterfClone,dCounter);
		newWorker.ForkAndSpin();
		myWorkers.Append(newWorker);
		//AddMessage_Factory(newWorker,start+i,buffer,myInterfClone);
		//start += 10;
	}
	myWorkers.MoveToStart();
	cout<<"myWorkers.LeftLength() "<<myWorkers.LeftLength()<<endl;

	cout<<"myWorkers.RightLength() "<<myWorkers.RightLength()<<endl;
}
#endif

//Handling the fill message from the Generator

MESSAGE_HANDLER_DEFINITION_BEGIN(MasterImp, PushNumber, FillMessage)
	
	//cout<<"Got the fill Message - Master "<<msg.number<<endl;	

	evProc.buffer.push_back(msg.number);
	
	int bufferSize = (int)evProc.buffer.size();

	if(bufferSize%10 == 0 ){
		// Create the workers and send the message to do the sum
		//cout<<"Sent the subset to Worker-Master "<<msg.number<<endl;	
		evProc.myWorkers.MoveToStart();
		EventProcessor currentWorker;
		if(evProc.myWorkers.Length() != 0){
			evProc.myWorkers.Remove(currentWorker);

			//EventProcessor& currentWorker = evProc.myWorkers.Current();
			//evProc.myWorkers.Advance();	

			EventProcessor myInterfClone;
			myInterfClone.CopyFrom(evProc.myInterface);
			AddMessage_Factory(currentWorker, evProc.current,evProc.buffer,myInterfClone);
			evProc.current += 10;
		}
	}
	
	EventProcessor myInterfClone;
	myInterfClone.CopyFrom(evProc.myInterface);

	NextNumberMessage_Factory(msg.sender,0,myInterfClone);

MESSAGE_HANDLER_DEFINITION_END

//Handling the message sent by worker signalling sum is done

MESSAGE_HANDLER_DEFINITION_BEGIN(MasterImp, SumDone, DoneMessage)
	
	evProc.sum += msg.sum;
	//evProc.myWorkers.Append(msg.sender);
	//cout<<"No of workers available - Master "<<evProc.myWorkers.Length()<<endl;

MESSAGE_HANDLER_DEFINITION_END

//This message indicates that all the generators are done

MESSAGE_HANDLER_DEFINITION_BEGIN(MasterImp, GenDone, GenDoneMessage)
		
	evProc.generatorsDone = true;
	cout<<"Got GenDone Message - Master"<<endl;
//	evProc.Seppuku();

MESSAGE_HANDLER_DEFINITION_END

//Workers are ready to do the sum 

MESSAGE_HANDLER_DEFINITION_BEGIN(MasterImp, WorkerReady, ReadyMessage)
	
//	cout<<"Worker Ready - Master"<<endl;	
	evProc.myWorkers.Append(msg.sender);
	cout<<"Worker Ready - Master "<<evProc.myWorkers.Length()<<endl;
//	EventProcessor myInterfClone;
//	myInterfClone.CopyFrom(evProc.myInterface);
//	AddMessage_Factory(msg.sender,0,evProc.buffer,myInterfClone);
//	evProc.myWorkers.Append(msg.sender);

MESSAGE_HANDLER_DEFINITION_END

MESSAGE_HANDLER_DEFINITION_BEGIN(MasterImp, Die, DieMessage)
#if 0	
	if(evProc.generatorsDone == true){
		cout<<"Everybody is done !!!"<<endl;
		evProc.myWorkers.MoveToStart();
		while(evProc.myWorkers.RightLength() == 0){
			EventProcessor &newWorker = evProc.myWorkers.Current();
			KillEvProc(newWorker);
			evProc.myWorkers.Advance();
		}
		evProc.EventProcessorImp::processDieMessage(evProc,msg);
		cout<<"Sum is "<<evProc.sum<<endl;
	}	
	else{
		cout<<"Generators not yet done "<<endl;
	}

#endif
	cout<<"The sum is "<<evProc.sum<<endl;
	cout<<"The correct outcome is 5050"<<endl;
	evProc.EventProcessorImp::processDieMessage(evProc,msg);

MESSAGE_HANDLER_DEFINITION_END

